package com.demo.springai.service;

import com.demo.springai.model.ChatRequest;
import com.demo.springai.model.ChatResponse;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Map;

/**
 * 聊天服务类
 * 负责处理与AI的对话逻辑
 * 
 * 注意：这个版本是简化版本，主要展示如何构建Spring AI应用的基础结构
 * 实际的AI功能需要配置正确的API密钥后才能使用
 * 
 * 当前版本提供模拟响应，展示完整的接口结构
 */
@Slf4j  // Lombok注解：自动生成日志对象
@Service  // Spring注解：标记为服务层组件
public class ChatService {

    /**
     * API密钥配置状态
     */
    @Value("${spring.ai.openai.api-key:your-openai-api-key-here}")
    private String apiKey;

    /**
     * AI服务可用性状态
     */
    private final boolean aiServiceAvailable;

    /**
     * 会话历史存储
     * 在实际项目中，建议使用Redis或数据库存储
     */
    private final Map<String, List<String>> sessionHistory = new ConcurrentHashMap<>();

    /**
     * 构造函数：注入依赖
     *
     * @param aiServiceAvailable AI服务可用性状态
     */
    @Autowired
    public ChatService(boolean aiServiceAvailable) {
        this.aiServiceAvailable = aiServiceAvailable;
        log.info("ChatService initialized. AI Service Available: {}", aiServiceAvailable);
    }

    /**
     * 处理基础聊天请求
     * 这是最简单的聊天方式，发送消息并等待完整响应
     *
     * @param request 聊天请求
     * @return 聊天响应
     */
    public ChatResponse chat(ChatRequest request) {
        // 记录开始时间，用于计算处理时长
        long startTime = System.currentTimeMillis();
        
        try {
            log.debug("Processing chat request: {}", request.getMessage());

            // 验证请求
            if (!request.isValid()) {
                return ChatResponse.error("请求无效：消息不能为空", "INVALID_REQUEST");
            }

            // 生成AI响应（当前版本使用模拟响应）
            String aiMessage = generateMockResponse(request.getMessage());
            String modelUsed = request.getModel() != null ? request.getModel() : "mock-ai-model";

            // 创建成功响应
            ChatResponse response = ChatResponse.success(aiMessage, modelUsed, request.getSessionId());
            
            // 设置消息ID
            response.setMessageId(UUID.randomUUID().toString());
            
            // 设置处理时间
            response.setProcessingTime(startTime);

            // 设置模拟的token使用信息
            response.setTokenUsage(calculateTokens(request.getMessage()), calculateTokens(aiMessage));

            // 如果有会话ID，保存对话历史
            if (request.getSessionId() != null) {
                saveToHistory(request.getSessionId(), request.getMessage(), aiMessage);
            }

            log.debug("Chat response generated successfully for session: {}", request.getSessionId());
            return response;

        } catch (Exception e) {
            log.error("Error processing chat request: {}", e.getMessage(), e);
            
            ChatResponse errorResponse = ChatResponse.error(
                "处理聊天请求时发生错误: " + e.getMessage(), 
                "PROCESSING_ERROR"
            );
            errorResponse.setProcessingTime(startTime);
            return errorResponse;
        }
    }

    /**
     * 处理流式聊天请求（简化版本）
     * 当前版本不支持真正的流式响应，返回模拟的分块响应
     *
     * @param request 聊天请求
     * @return 模拟的流式响应
     */
    public String chatStream(ChatRequest request) {
        try {
            log.debug("Processing stream chat request: {}", request.getMessage());

            // 验证请求
            if (!request.isValid()) {
                return "错误：请求无效，消息不能为空";
            }

            // 生成模拟的流式响应
            String response = generateMockResponse(request.getMessage());
            
            // 在实际的Spring AI应用中，这里会返回真正的流式响应
            // 当前版本返回完整响应，展示接口结构
            return "流式响应：" + response;

        } catch (Exception e) {
            log.error("Error starting stream chat: {}", e.getMessage(), e);
            return "启动流式聊天时发生错误: " + e.getMessage();
        }
    }

    /**
     * 获取会话历史
     *
     * @param sessionId 会话ID
     * @return 历史消息列表
     */
    public List<String> getSessionHistory(String sessionId) {
        return sessionHistory.getOrDefault(sessionId, List.of());
    }

    /**
     * 清除会话历史
     *
     * @param sessionId 会话ID
     */
    public void clearSessionHistory(String sessionId) {
        sessionHistory.remove(sessionId);
        log.debug("Cleared history for session: {}", sessionId);
    }

    /**
     * 生成模拟AI响应
     * 当前版本使用模拟响应，展示接口结构
     * 在实际项目中，这里会调用真正的AI服务
     *
     * @param userMessage 用户消息
     * @return 模拟的AI响应
     */
    private String generateMockResponse(String userMessage) {
        if (!aiServiceAvailable) {
            return String.format(
                "您好！当前使用的是模拟AI响应。要启用真正的AI功能，请：\n" +
                "1. 获取OpenAI API密钥\n" +
                "2. 在application.yml中配置spring.ai.openai.api-key\n" +
                "3. 重启应用\n\n" +
                "您的原始消息：%s", userMessage
            );
        }
        
        // 如果API密钥已配置但这里仍然使用模拟响应，说明需要集成真正的AI服务
        return String.format(
            "这是对您消息的模拟回复：%s\n\n" +
            "[注意：这是模拟响应，实际使用时会调用真正的AI服务]", userMessage
        );
    }
    
    /**
     * 计算文本的token数量（模拟）
     * 在实际项目中，应该使用真正的tokenizer
     *
     * @param text 文本内容
     * @return 估算的token数
     */
    private int calculateTokens(String text) {
        if (text == null || text.trim().isEmpty()) {
            return 0;
        }
        // 简单的估算：平均每4个字符算作1个token
        return Math.max(1, text.length() / 4);
    }

    /**
     * 保存对话历史到内存
     * 在实际项目中，应该保存到数据库或Redis
     *
     * @param sessionId   会话ID
     * @param userMessage 用户消息
     * @param aiMessage   AI回复
     */
    private void saveToHistory(String sessionId, String userMessage, String aiMessage) {
        sessionHistory.computeIfAbsent(sessionId, k -> new java.util.ArrayList<>())
                .addAll(List.of(
                    "User: " + userMessage,
                    "AI: " + aiMessage
                ));
        
        // 限制历史记录长度，避免内存溢出
        List<String> history = sessionHistory.get(sessionId);
        if (history.size() > 20) {
            history.subList(0, history.size() - 20).clear();
        }
    }
}
